#include <stdio.h> // for printf
#include <string.h> // for memory operation
#include <stdlib.h>
#include <unistd.h> // for sleep
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_i2c.h"
#include "iot_i2c_ex.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"

//I2C引脚
#define I2C_SDA_GPIO_IDX 0
#define I2C_SCL_GPIO_IDX 1
//I2C序号
#define WIFI_IOT_I2C_IDX_0 1
#define SHT30_ADDR 0x44
#define I2C_WRITE_FLAG 0

// void TASK1(void){
//     initI2C();
//     //初始化sht30
//     InitSHT30();
//     //读取数据
//     while(1){
//         SHT3X_ReadMeasurementBuffer(&temp,&humi);
//         printf("==> temp=%f,humi=%f\n",temp,humi);
//         //每5秒读取一次
//         sleep(5);
//     }
// }
//初始化I2C
void initI2C(){
    //初始化io
    IoTGpioInit(I2C_SDA_GPIO_IDX);
    // GPIO_13复用为I2C1_SDA
    IoTGpioSetFunc(I2C_SDA_GPIO_IDX, IOT_GPIO_FUNC_GPIO_0_I2C1_SDA); 
    IoTGpioInit(I2C_SCL_GPIO_IDX);
    // GPIO_14复用为I2C1_SCL
    IoTGpioSetFunc(I2C_SCL_GPIO_IDX, IOT_GPIO_FUNC_GPIO_1_I2C1_SCL); 
    //初始化I2C并设置波特率
    IoTI2cInit(WIFI_IOT_I2C_IDX_0, 400000);
}
//初始化SHT30芯片
int InitSHT30(void)
{
    int ret;
    uint8_t send_data[2] = {0x22, 0x36};
    ret = IoTI2cWrite(WIFI_IOT_I2C_IDX_0, (SHT30_ADDR << 1) |I2C_WRITE_FLAG, send_data, 2);
    if (ret != 0) {
        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
        return -1;
    }
    return 0;
}
/***************************************************************
* 函数名称: SHT3xCheckCrc
* 说    明: 检查数据正确性
* 参    数: data：读取到的数据
            nbrOfBytes：需要校验的数量
            checksum：读取到的校对比验值
* 返 回 值: 校验结果，0-成功    1-失败
***************************************************************/
uint8_t SHT3xCheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)
{
  uint8_t crc = 0xFF;
  uint8_t bit = 0;
  uint8_t byteCtr;
  const int16_t POLYNOMIAL = 0x131;
  // calculates 8-Bit checksum with given polynomial
  for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr) {
    crc ^= (data[byteCtr]);
    for (bit = 8; bit > 0; --bit) {
      if (crc & 0x80)
        crc = (crc << 1) ^ POLYNOMIAL;
      else
        crc = (crc << 1);
    }
  }
  if (crc != checksum)
    return 1;
  else
    return 0;
}
/***************************************************************
 * 函数名称: SHT3xCalcTemperatureC
 * 说    明: 温度计算
 * 参    数: u16sT：读取到的温度原始数据
 * 返 回 值: 计算后的温度数据
 ***************************************************************/
float SHT3xCalcTemperatureC(uint16_t u16sT)
{
    float temperatureC = 0; // variable for result
    //-- calculate temperature [℃] --
    temperatureC = (175 * (float)u16sT / 65535 - 45); // T = -45 + 175 * rawValue / (2^16-1)
    return temperatureC;
}
/***************************************************************
 * 函数名称: SHT3xCalcRH
 * 说    明: 湿度计算
 * 参    数: u16sRH：读取到的湿度原始数据
 * 返 回 值: 计算后的湿度数据
 ***************************************************************/
float SHT3xCalcRH(uint16_t u16sRH)
{
    float humidityRH = 0; // variable for result
    u16sRH &= ~0x0003;  // clear bits [1..0] (status bits)
    //-- calculate relative humidity [%RH] --
    humidityRH = (100 * (float)u16sRH / 65535); // RH = rawValue / (2^16-1) * 10
    return humidityRH;
}
int SHT3X_ReadMeasurementBuffer(float *temperature,float *humidity)
{
    int ret;
    uint8_t data[3]; // data array for checksum verification
    uint16_t dat, tmp;
    uint8_t SHT3X_Data_Buffer[6]; // byte 0,1 is temperature byte 4,5 is humidity
    IotI2cData sht30_i2c_data = {0};
    uint8_t send_data[2] = {0xE0, 0x00};
    sht30_i2c_data.sendBuf = send_data;
    sht30_i2c_data.sendLen = 2;
    sht30_i2c_data.receiveBuf = SHT3X_Data_Buffer;
    sht30_i2c_data.receiveLen = 6;
    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_0, (SHT30_ADDR << 1) | 0x00, &sht30_i2c_data); // Read bh1750 sensor data
    if (ret != 0) {
        return -1;
    }
    /* check tem */
    data[0] = SHT3X_Data_Buffer[0];
    data[1] = SHT3X_Data_Buffer[1];
    data[2] = SHT3X_Data_Buffer[2];
    tmp = SHT3xCheckCrc(data, 2, data[2]);
    /* value is ture */
    if (!tmp) {
        dat = ((uint16_t)data[0] << 8) | data[1];
        *temperature = SHT3xCalcTemperatureC(dat);
    }else return -1;
    /* check humidity */
    data[0] = SHT3X_Data_Buffer[3];
    data[1] = SHT3X_Data_Buffer[4];
    data[2] = SHT3X_Data_Buffer[5];
    /* value is ture */
    tmp = SHT3xCheckCrc(data, 2, data[2]);
     if (!tmp) {
        dat = ((uint16_t)data[0] << 8) | data[1];
        *humidity = SHT3xCalcRH(dat);
    }else return -1;
}